/*!
    \copyright  Copyright (c) 2024 Qualcomm Technologies International, Ltd.
                All Rights Reserved.
                Qualcomm Technologies International, Ltd. Confidential and Proprietary.
    \version    
    \file       dult.h
    \addtogroup dult
    \brief      Header file for the DULT component (Detecting Unwanted Location Trackers).
    @{
*/

#include <logging.h>
#include "dult.h"
#include "dult_advertiser.h"
#include "message.h"

#define DULT_SEPARATE_MODE_TIMEOUT             (D_MIN(30))
#define DULT_DISABLE_TIMEOUT                   (D_HOUR(24))

/*! \brief Global data structure for the DULT component */
typedef struct
{
    /*! The DULT advertising module task */
    TaskData task;
    bool enabled;
    bool near_owner;
} dult_data_t;

/*! Global Instance of dult advertising data */
dult_data_t dult;

typedef enum
{
    DULT_INTERNAL_SEPARATE_MODE_TIMEOUT,
    DULT_INTERNAL_DISABLE_TIMEOUT
} dult_internal_msgs_t;

static Task dult_GetTask(void)
{
    return (&dult.task);
}

static bool dult_IsDisablingPending(Task task, MessageId id, Message payload)
{
    UNUSED(payload);
    
    return task == dult_GetTask() && id == DULT_INTERNAL_DISABLE_TIMEOUT;
}

static void dult_HandleMessage(Task task, MessageId id, Message message)
{
    UNUSED(task);
    UNUSED(message);

    switch (id)
    {
        case DULT_INTERNAL_DISABLE_TIMEOUT:
        {
            DEBUG_LOG_INFO("dult_HandleMessage, DULT_INTERNAL_DISABLE_TIMEOUT timeout, disabling DULT");
            dult_DisableAdvertising();
        }
        break;
        case DULT_INTERNAL_SEPARATE_MODE_TIMEOUT:
        {
            DEBUG_LOG_INFO("dult_HandleMessage, DULT_INTERNAL_SEPARATE_MODE_TIMEOUT timeout, entering separate mode");
            dult_SetNearOwner(false);
        }
        break;
    }
}

void Dult_Init(void)
{
    DEBUG_LOG("Dult_Init");
    dult_InitAdvertising();
    dult_GetTask()->handler = dult_HandleMessage;
}

void Dult_SetCompanyPayload(const uint8_t *const payload, const size_t payload_size)
{
    dult_SetProprietaryPayload(payload, payload_size);
}

le_adv_item_data_t Dult_GetAdvItemData(void)
{
    return dult_GetDultAdvData();
}

void Dult_SetAdvAddress(bdaddr addr)
{
    dult_SetAdvAddress(addr);
}

void Dult_IndicateNearOwner(void)
{
    dult.near_owner = TRUE;
    dult_SetNearOwner(dult.near_owner);

    MessageCancelAll(dult_GetTask(), DULT_INTERNAL_SEPARATE_MODE_TIMEOUT);
}

void Dult_IndicateSeparated(bool eagerly)
{
    if(eagerly)
    {
        dult.near_owner = FALSE;
        dult_SetNearOwner(dult.near_owner);
        return;
    }

    MessageSendLater(dult_GetTask(), DULT_INTERNAL_SEPARATE_MODE_TIMEOUT, NULL, DULT_SEPARATE_MODE_TIMEOUT);
}

void Dult_Enable(void)
{
    DEBUG_LOG("Dult_Enable");
    dult.enabled = TRUE;
    dult_EnableAdvertising();

    MessageCancelAll(dult_GetTask(), DULT_INTERNAL_DISABLE_TIMEOUT);
}

void Dult_Disable(void)
{
    DEBUG_LOG("Dult_Disable");
    /* Don't reset the timer if it's been previously disabled */
    if(!MessagePendingMatch(dult_GetTask(), TRUE, &dult_IsDisablingPending))
    {
        MessageSendLater(dult_GetTask(), DULT_INTERNAL_DISABLE_TIMEOUT, NULL, DULT_DISABLE_TIMEOUT);
    }
}

bool Dult_IsEnabled(void)
{
    return dult.enabled;
}
